﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using StructureMap;
using System.Data;
using MySql.Data.MySqlClient;
using StructureMap.Pipeline;
using System.Threading;
using NUnit.Framework;
using NHibernate;

namespace ConsoleApp.StructureMap
{
    public class StructureMapTest
    {
        IContainer _container;

        [TestFixtureSetUp] 
        public void FixtureSetup()
        {
            _container = new Container(x =>
            {
                x.For<IService>().Singleton().Use<IService>();
                x.For<IRepository>().Singleton().Use<IRepository>();

                x.For<IDbConnection>().Singleton()
                    .Use(c =>
                        new MySqlConnection("Server=127.0.0.1;Port=3306;Database=bbtest;Uid=root;Pwd=root;charset=utf8;")
                        );
            });
        } 

        [Test]
        public void IService_should_be_singleton()
        {
            var service1 = _container.GetInstance<IService>();
            var service2 = _container.GetInstance<IService>();
            Assert.That(service1, Is.SameAs(service2)); 
        }

        [Test]
        public void IRepository_should_be_singleton()
        {
            var service1 = _container.GetInstance<IRepository>();
            var service2 = _container.GetInstance<IRepository>();
            Assert.That(service1, Is.SameAs(service2));
        } 

        static IContainer Initialize()
        {
            var container = new Container(x =>
            {
                x.For<ISessionFactory>().Singleton().Use(c => NHibernateBootstrapper.SessionFactory);

                x.For<ISession>().LifecycleIs(new UniquePerRequestLifecycle()).Use(c =>
                {
                    return c.GetInstance<ISessionFactory>().OpenSession();
                });

                x.For<IService>().Singleton().Use<Service>();
                x.For<IRepository>().Singleton().Use<Repository>();

                x.For<IDbConnection>().HybridHttpOrThreadLocalScoped()
                    .Use(c =>
                        new MySqlConnection("Server=127.0.0.1;Port=3306;Database=bbtest;Uid=root;Pwd=root;charset=utf8;")
                        );

                
            });

            return container;
        }

        public static void demo()
        {
            var container = Initialize();

            ISessionFactory s1 = container.GetInstance<ISessionFactory>();
            ISessionFactory s2 = container.GetInstance<ISessionFactory>();

            IService service = null; IService service1 = null; IService service2 = null;
            IRepository repository, repository1, repository2;
            IDbConnection dbConnection, dbConnection1, dbConnection2;

            //Thread thread = new Thread(() =>
            //{
                service = container.GetInstance<IService>();
                repository = container.GetInstance<IRepository>();
                dbConnection = container.GetInstance<IDbConnection>();
            //});

            //Thread thread1 = new Thread(() =>
            //{
                service1 = container.GetInstance<IService>();
                repository1 = container.GetInstance<IRepository>();
                dbConnection1 = container.GetInstance<IDbConnection>();
            //});

            //Thread thread2 = new Thread(() =>
            //{
                service2 = container.GetInstance<IService>();
                repository2 = container.GetInstance<IRepository>();
                dbConnection2 = container.GetInstance<IDbConnection>();   
            //});

            //thread.Start();
            //thread1.Start();
            //thread2.Start();

            Thread.Sleep(1000 * 100);

            if (service1 == service2)
            {

            }
        }
    }

    public interface IService
    {
        IRepository GetRepository();
    }

    public interface IRepository
    {
        IDbConnection GetDbConnection();
    }

    public class Service : IService
    {
        private IRepository _repository;

        public Service(IRepository repository)
        {
            _repository = repository;
        }

        public IRepository GetRepository()
        {
            return _repository;
        }
    }

    public class Repository : IRepository
    {
        private IDbConnection _dbConnection;

        public Repository(ISession session)
        {
            _dbConnection = session.Connection;
        }

        public IDbConnection GetDbConnection()
        {
            return _dbConnection;
        }
    }
}